package com.ifi.client.controller;

import ifi.card.poker.Poker;

import java.util.List;

public class GameController {

	public static int PLAYING_FLAT_SINGLE 		= 1;
	public static int PLAYING_FLAT_DOUBLE 		= 2;
	public static int PLAYING_FLAT_TRIPLE 		= 3;
	public static int PLAYING_FLAT_QUADRUPLE 	= 4;
	public static int PLAYING_SEQUENCE 			= 0;
	public static int PLAYING_UNDEFINED			= -1;
	
	public static int SUIT_HEART 	= 3; // COEURS ♥
	public static int SUIT_DIAMON 	= 2; // CARREAUX ♦
	public static int SUIT_CLUB 	= 1; // TREFLES ♣
	public static int SUIT_SPADE 	= 0; // PIQUES ♠
	public static int MASTER_CARD	= 15;// 2 card
	
	private int lastValues[];
	private int lastSuits[];
	
	public GameController(){}
	
	// Checking when player try to playing game!
	// input: @param cardValues[] array of integer values that present for value 3,4,...J,Q,K,A,2
	// 		  @param cardSuits[]  array of integer values that present for 
	//								suits of card: ♥♦♣♠ ~ 3,2,1,0
	//		  all 2 array have similar size, that maximum size is 13 (= 52/4)
	// output: check in local rule, if ok return true and inverse
	private boolean check(int cardValues[], int cardSuits[]){
		if(cardValues == null || cardSuits == null) 
			return false;
		
		int oldCards[] = getPreviousCards();// Khoi tao tam
		int oldSuits[] = getPreviousSuits(); // Khoi tao tam
		int currentPlayingType = getTypeOfRound(oldCards, cardValues);
		if(currentPlayingType == PLAYING_UNDEFINED)
			return false;
		if (currentPlayingType == PLAYING_FLAT_SINGLE) {
			// Kiem tra neu khac chat thi return FALSE
			int newCard = cardSuits[0];
			// Neu la 2 bo qua kiem tra chat
			if(newCard == 15)
				return true;
			else// Neu khong thi tra lai ket qua kiem tra chat 
				return checkIdenticalSuits(oldSuits, cardSuits);
		}
		if (currentPlayingType == PLAYING_FLAT_DOUBLE) {
			// Kiem tra neu la 2doi 2 chat 2 doi 2
			// DOAN NAY PHAI KIEM TRA LAI
			// TEST : CHAC CHAN ca 2 quan bai moi deu la 2
			// case quan cu #2, quan cu~~2
			if (minValue(cardValues) == 2 && maxValue(oldCards) == 2) {
				return checkAcceptMasterCard(oldSuits, cardSuits);
			} else {// Truong hop binh thuong
				// if color is Black-Red -> return FALSE
				int color = cardSuits[0] + cardSuits[1];
				if ((color % 2) == 0)
					return false;
				// if newValue < oldValue -> return FALSE
				if (checkValidMinMax(oldCards, cardValues)) {
					return checkIdenticalSuits(oldSuits, cardSuits);
				} else {
					return false;
				}
			}
		}
		if (currentPlayingType == PLAYING_FLAT_TRIPLE) {
			// Kiem tra neu la 3 con 2 thi bo qua kiem tra chat
			if(minValue(cardValues)==2)
				return true;
			else
				return checkIdenticalSuits(oldSuits, cardSuits);
		}
		if (currentPlayingType == PLAYING_FLAT_QUADRUPLE) {
			// Kiem tra 4 quy chat 2 thi cho phep
			if(oldCards[0]==2)
				return true;
			else// Kiem tra gia tri 4 quy sau > tu quy truoc
				return checkValidMinMax(oldCards, cardValues);
		}
		if (currentPlayingType == PLAYING_SEQUENCE) {
			// Kiem tra neu dong chat
			if(checkIdenticalSuits(oldSuits, cardSuits)){
				//Kiem tra neu gia tri sau > gia tri truoc
				return checkValidMinMax(oldCards, cardValues);
			}else// neu khong dong chat return FALSE
				return false;
		}

		return false;
	}
	
	// Send to server
	// Check rules from local first, and then send to game server
	// Open connection, send to server request PLAY with parameters which are int[], int[] 
	public boolean play(List<Poker> cards, int[] lastValues, int[] lastMatier){
		int cardsValues[] = new int[cards.size()];
		int cardsSuits[] = new int[cards.size()];
		// For local testing -----------
		this.lastValues = lastValues;
		this.lastSuits = lastMatier;
		// For local testing -----------
		
		for(int i = 0; i < cards.size(); i++){
			Poker p = cards.get(i);
			// Assigne value for 2 arrays Values & Suits
			cardsValues[i] = p.numPoker;
			cardsSuits[i] = p.matier;
		}
		if(check(cardsValues, cardsSuits)){
			// Open connection to server, then PLAY!
			return true;
		}
		return false;
	}
	
	// Search from server all tables of game which are available
	public int findTable(){
		return 0;
	}
	
	public int selectTable(){
		return 0;
	}
	
	public boolean startAGame(){
		return true;
	}
	
	public int[] getMyCards(){
		int result[] = new int[13];// Khoi tao tam thoi
		// Request server de lay ve bai cua minh
		return result;
	}
	
	private int getTypeOfRound(int[] oldCards, int[] newCards){
		if(oldCards.length == newCards.length){
			// Kiem tra neu kieu choi la FLAT
			if(checkFlat(newCards))
				return newCards.length;
			else if(checkContinue(newCards))
				return PLAYING_SEQUENCE;
			else 
				return PLAYING_UNDEFINED;
		}else{// Truong hop 4 quy chat 2
			if(oldCards.length == 1 && newCards.length == 4 && checkFlat(newCards))
				return PLAYING_FLAT_QUADRUPLE;
		}
		return PLAYING_UNDEFINED;
	}
	
	// Get list of card in the lastest round
	private int[] getPreviousCards(){
		// Fake du lieu
		int fake[] = {1,2,3,5,4};
		
		//return fake;
		return lastValues;
	}
	
	private int[] getPreviousSuits(){
		// Fake du lieu
		int fake[] = {0,1,1,1};
		//return fake;
		return lastSuits;
	}

	// Checking when player send multicard at the same moment.
	private boolean checkMulticard(){
		// Checking type = multicard-flat
		// Checking type = multicard-non-flat
		return false;
	}
	
	// Check list of cards is continue
	// Check in case playing with multicard not-flat
	private boolean checkContinue(int array[]){
		for(int i = 0; i < array.length - 1; i++)
			if(array[i] + 1 != array[i+1])
				return false;
		return true;
	}
	
	// Checking play-type is multicard-flat
	private boolean checkFlat(int array[]){
		for(int i = 0; i < array.length - 1; i++)
			if(array[i] != array[i+1])
				return false;
		return true;
	}
	
	// Kiem tra chat khi danh' voi truong hop co'
	private boolean checkIdenticalSuits(int oldSuits[], int newSuits[]){
		int sumOldSuits = 0;
		int sumNewSuits = 0;
		int size = oldSuits.length;
		for(int i = 0; i < size; i++){
			sumOldSuits += oldSuits[i];
			sumNewSuits += newSuits[i];
		}
		if(sumOldSuits == sumNewSuits)
			return true;
		return false;
	}
	
	// MasterCard : 2 - quan bai lon nhat tren ban choi
	// Kiem tra duoc phep 2 chat 2 khong (2♥ > 2♦  > 2♣ > 2♠)
	private boolean checkAcceptMasterCard(int oldSuits[], int newSuits[]){
		int sumOldSuits = 0;
		int sumNewSuits = 0;
		for(int i = 0; i < oldSuits.length; i++){
			sumOldSuits += oldSuits[i];
			sumNewSuits += newSuits[i];
		}
		if(sumOldSuits < sumNewSuits)
			return true;
		return false;
	}
	
	// Kiem tra gia tri bai danh sau sau co' > gia  tri bai da danh truoc' khong
	private boolean checkValidMinMax(int oldCards[], int newCards[]){
		int oldMax = Integer.MIN_VALUE;
		int newMin = Integer.MAX_VALUE;
		for(int i = 0; i < oldCards.length; i++){
			if(oldMax < oldCards[i]){
				oldMax = oldCards[i];
			}
			if(newMin > newCards[i]){
				newMin = newCards[i];
			}
		}
		if(newMin > oldMax)
			return true;
		return false;
	}
	
	private int maxValue(int array[]){
		return 0;
	}
	
	private int minValue(int array[]){
		return 0;
	}
	
}
